#include <stdio.h>
#include <stdlib.h>
#include "utilis.hh"

#include "local_search_neighborhood_randomly.hh"


pair<Graph*, PathMatrix*> * SelectOneRandomAndClearTheRest(list< pair<Graph*, PathMatrix*> * > *  G_nodes_union_G_edges)
{
	int index = Random(G_nodes_union_G_edges->size());

	list< pair<Graph*, PathMatrix*>* >::iterator it1 = G_nodes_union_G_edges->begin();
	advance(it1, index);
	pair<Graph*, PathMatrix*> * elem = (*it1);

	 for (list< pair<Graph*, PathMatrix*>* >::iterator it=G_nodes_union_G_edges->begin(); it != G_nodes_union_G_edges->end(); ++it)
			if (it!= it1) DeletePair(*it);

	 G_nodes_union_G_edges->clear();

	return elem;
}

int LocalSearchNeighborhoodRandomly(Graph * G_problem, int k, Graph *& G_sol, PathMatrix *& P_sol, double alpha, double beta, int size_pool) {

	list< pair<Graph*, PathMatrix*> * > * NNodes = NeighborhoodByEliminatingNodes(G_problem, G_sol, P_sol, k, beta, size_pool);
	list< pair<Graph*, PathMatrix*> * > * NEdges = NeighborhoodByEliminatingEdges(G_problem, G_sol, P_sol, k, alpha, size_pool);

	list< pair<Graph*, PathMatrix*> * > *  G_nodes_union_G_edges = new list< pair<Graph*, PathMatrix*> * >();

	// Hago el checkeo de costo y voy armando la union
	 for (list< pair<Graph*, PathMatrix*>* >::iterator it=NNodes->begin(); it != NNodes->end(); ++it) {
			if ((*it)->first->Cost() < G_sol->Cost()) {
				G_nodes_union_G_edges->push_front((*it));
			}
			else
				DeletePair(*it);
	 }

	 for (list< pair<Graph*, PathMatrix*> *>::iterator it=NEdges->begin(); it != NEdges->end(); ++it) {
			if ((*it)->first->Cost() < G_sol->Cost()) {
				G_nodes_union_G_edges->push_front((*it));
			}
			else
				DeletePair(*it);
	 }

	 //cout << "SIZE: " << NNodes->size() + NEdges->size() << endl;
	 NNodes->clear();
	 delete NNodes;
	 NEdges->clear();
	 delete NEdges;

	while (!G_nodes_union_G_edges->empty()) {

		pair<Graph*, PathMatrix*> * elem = SelectOneRandomAndClearTheRest(G_nodes_union_G_edges);

		delete G_sol;
		delete P_sol;

		G_sol = elem->first;
		P_sol = elem->second;

		delete elem;

		NNodes = NeighborhoodByEliminatingNodes(G_problem, G_sol, P_sol, k, beta, size_pool);
		NEdges = NeighborhoodByEliminatingEdges(G_problem, G_sol, P_sol, k, alpha, size_pool);

		// Hago el checkeo de costo y voy armando la union
		 for (list< pair<Graph*, PathMatrix*>* >::iterator it=NNodes->begin(); it != NNodes->end(); ++it) {
				if ((*it)->first->Cost() < G_sol->Cost()) {
					G_nodes_union_G_edges->push_front((*it));
				}
				else
					DeletePair(*it);
		 }

		 for (list< pair<Graph*, PathMatrix*> *>::iterator it=NEdges->begin(); it != NEdges->end(); ++it) {
				if ((*it)->first->Cost() < G_sol->Cost()) {
					G_nodes_union_G_edges->push_front((*it));
				}
				else
					DeletePair(*it);
		 }

		 //cout << "SIZE: " << NNodes->size() + NEdges->size() << endl;
		 NNodes->clear();
		 delete NNodes;
		 NEdges->clear();
		 delete NEdges;
	}

	delete G_nodes_union_G_edges;

	return 0;
}
